// This file is part of streaminfo.
//
// Foobar is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//  
// Foobar is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//  
// You should have received a copy of the GNU General Public License
// along with Foobar.  If not, see <http://www.gnu.org/licenses/>.

#include <cstdio>
#include <unistd.h>
#include <malloc.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#include <string>

#include "stream_summary.h"
#include "count.h"

static char *buffer;            /* Base of buffer. */

int CSTRING_BUFFER_LENGTH = 128;
int MAX_COUNTERS = 2;

static char *
cstring_alloc(FILE* f, int depth)
{
    char *cstring;
    char buffer[CSTRING_BUFFER_LENGTH];
    int  target = CSTRING_BUFFER_LENGTH * depth;
    int  i, len;
    size_t size;

    /* fill buffer */
    i = 0;
    while ((buffer[i] = fgetc(f)) != EOF) {
                if (buffer[i++] == 0x0a) { break; }
                if (i == CSTRING_BUFFER_LENGTH) { break; }
    }
    len = i;

    /* recurse or malloc? */
    if (len == CSTRING_BUFFER_LENGTH) {
                cstring = cstring_alloc(f, (depth + 1));
    } else {
                /* [special case] EOF */
                if ((depth | len) == 0) { return NULL; }

                /* malloc */
                size = target + len + 1;
                cstring = reinterpret_cast<char*>(malloc(size));
                if (!cstring) { return NULL; }
                cstring[size - 1] = 0;
    }

    /* copy buffer */
    if (cstring) {
                memcpy(&cstring[target], buffer, len);
    }
    return cstring;
}

/*
 * wrapper around recursive cstring_alloc
 * it's the caller's responsibility to free the cstring
 */
char *
cstring_lineFromFile(FILE *f)
{
    return cstring_alloc(f, 0);
}

void do_heavy_hitters (heavy_hitters<std::string> &hitters,count &counting, char* str)
{
  const char *delimiters = " \n\r";
  char *token = strtok(str,delimiters);
  while(token) 
    {
      std::string new_string(token);
      hitters.heavy_hitters_add(new_string);
      counting.add(new_string);
      token = strtok(NULL,delimiters);
    }
}

void int_heavy_hitters(heavy_hitters<int> &hitters, char* str) {
  const char *delimiters = " \n\r";
  char *token = strtok(str,delimiters);
  while(token) {
    int int_token = atoi(token);
    hitters.heavy_hitters_add(int_token);
    hitters.print_buckets();
    token = strtok(NULL,delimiters);
  }
}

int
main (int argc, char **argv)
{
  int cc = 1;
  char *str = NULL;

  //heavy_hitters<std::string> hitters;
  heavy_hitters<std::string> hitters(40);
  count counting;

  while(cc)
    {
      str = cstring_lineFromFile(stdin);
      if(!str)
	break;
      do_heavy_hitters(hitters,counting, str);
      free(str);
    }
  counting.print();
  hitters.print_buckets();
  hitters.clear_counters();
}
